import { cloneDeep } from 'lodash';

// console.log(readData)

// console.log(writeData);

export function setOffsetIdFn(number: any = 0, byteLen = 2) {
  if (byteLen < 1) {
    return -1;
  }

  number = number.toString(16);

  for (let i = 2 * byteLen - number.length; i > 0; i--) {
    number = '0' + number;
  }

  number = number.toUpperCase();

  // number = number.length < 4 ? '0'.repeat(4 - number.length) + number : number;

  return number;
}

function resetDataFn(lItem: any, lastItem: any, offset: any, startOffset: any) {
  const lastIndex = lastItem ? lastItem.index : 0;

  const lastLeng = lastItem ? lastItem.leng : 0;

  const lastKeyLeng = lastItem ? lastItem.keyLeng : 0;

  const index = lastIndex + lastLeng / 2;

  // if (lItem.funId === 'homingStop') {
  //   console.log(lastItem);

  //   console.log(lastLeng);

  //   console.log(offset);

  //   console.log(startOffset);

  //   console.log(index);
  // }

  lItem.index = index;

  lItem.offsetIdNum = offset + startOffset + index;

  lItem.offsetId = setOffsetIdFn(offset + startOffset + index);

  lItem.keyLeng = lastLeng + lastKeyLeng;

  return lItem;
}

export const resetArrFn = (arr: any = []) => {
  const newArr: any = [];

  arr.forEach((item, _key) => {
    const { list = [] } = item;

    const newList: any = [];

    list.forEach((lItem, _lKey) => {
      const lastItem: any = newList.length === 0 ? null : newList[newList.length - 1];

      if (![null, undefined].includes(lItem.address16)) {
        const address16Arr = lItem.address16.toString().split('.');

        if (address16Arr.length === 2 && Number(address16Arr[1]) < 16) {
          if (address16Arr[0] === '0') {
            lItem.address = Number(address16Arr[1]);
          } else {
            // (n*16-1) +  (m+1)

            lItem.address = Number(address16Arr[0]) * 16 - 1 + (Number(address16Arr[1]) + 1);

            // console.log(lItem.address);
          }
        }
      }

      if (lastItem && ![null, undefined].includes(lItem.address)) {
        // console.log(lItem.address);
        const previousAddress = lastItem.address;

        if (![null, undefined].includes(previousAddress)) {
          // 4 - (lastItem.leng / 2 - 1);
          // lastItem.address + (lastItem.leng / 2 - 1) = lItem.address
          // 2+1 = 4
          if (lastItem.address + lastItem.leng / 2 !== lItem.address) {
            const num = lItem.address - (previousAddress + (lastItem.leng / 2 - 1)) - 1;

            newList.push({ leng: num * 2 });
          }
          // (n*16-1) +  (m+1)
        }
      }

      newList.push(lItem);
    });

    newArr.push({ ...item, list: newList });
  });

  return newArr || arr;
};

export function setOffsetNumFn(arr: any = [], type = 'read', _isConsole = false) {
  const newArr: any = resetArrFn(arr);

  const newArrList: any = [];

  newArr.forEach((item, _key) => {
    const {
      list = [],
      // offset = 0,
      // startOffset = 0,
      id = null,
      type: iType = null,
      plcId = null,
    } = item;

    // let newOffset = offset;

    let code: any = null;

    if (iType && type) {
      if (type === 'read') {
        switch (iType) {
          case 'M':
            code = 1;
            break;
          case 'D':
            code = 3;
            break;

          default:
            break;
        }
      } else if (type === 'write') {
        switch (iType) {
          case 'M':
            code = 5;
            break;
          case 'D':
            code = 6;
            break;

          default:
            break;
        }
      }
    }

    let newArr: any = [];

    let allLeng = 0;

    let newLastItem = null;

    // console.log(list)

    list.forEach((lItem, _lKey) => {
      const { offset = 0, startOffset = 0 } = item;

      const lastItem: any = newArr.length === 0 ? newLastItem : newArr[newArr.length - 1];

      const obj = resetDataFn(lItem, lastItem, offset, startOffset);

      // if (newArr && !newArr.length && obj.funId === undefined && obj.leng > 124) {
      //   item.offset =
      // }

      // console.log(iType);

      const lengNum = iType === 'D' ? 2048 : 4088;

      if (allLeng + (obj.leng || 0) > lengNum) {
        // if (type === 'write') {
        //   console.log(obj.keyLeng);

        //   console.log(newArr);
        // }
        if (newArr && newArr.length) {
          const first = newArr[0];

          const last = newArr.length > 2 ? newArr[newArr.length - 1] : null;

          if (first.funId === undefined) {
            allLeng -= first.leng;

            newArr.shift();
          }

          if (last && last.funId === undefined) {
            allLeng -= last.leng;

            newArr.pop();
          }
        }

        if (newArr && newArr.length) {
          // if (type === 'write') {
          //   console.log(lastItem.keyLeng);

          //   console.log(item.keyLeng);

          //   // console.log(newArr);
          // }

          newLastItem = obj;

          // if(newArrList.length){

          // }

          newArrList.push({
            ...item,
            addr: newArr[0].offsetId,
            leng: allLeng / 2,
            list: [...newArr],
          });

          // console.log(JSON.parse(JSON.stringify(newArr)));

          // console.log(obj);

          allLeng = 0;

          newArr = [];

          obj.keyLeng = 0;

          obj.index = 0;

          // console.log(obj);

          item.offset = 0;

          item.startOffset = obj.offsetIdNum;

          newLastItem = null;

          // console.log(111, item.startOffset);

          // newOffset = obj.keyLeng + 1;
        }
      }

      allLeng += obj.leng || 0;

      // if (isConsole) {
      //   console.log(allLeng);
      // }

      if (id && !obj.id) {
        obj.id = id;
      }

      if (plcId && !obj.plcId) {
        obj.plcId = plcId;
      }

      if (!obj.leng) {
        obj.leng = 2;
      }

      if (!obj.decimalPlaces) {
        obj.decimalPlaces = 0;
      }

      if (code && !obj.code && obj.funId) {
        obj.code = code;
      }

      if (obj.funId === undefined && newArr && !newArr.length) {
        allLeng = 0;

        // console.log(222, item.startOffset);

        item.startOffset = item.offset + item.startOffset + obj.leng / 2;

        item.offset = 0;

        // obj.leng = 0;

        // newLastItem = null;

        // console.log(item)
        // console.log(item.startOffset);

        // console.log(item);

        // console.log(item.offset);

        // console.log(333,item.startOffset);

        // console.log(obj);

        // console.log(allLeng);
      } else {
        if (newArr.length === 0) {
          obj.keyLeng = 0;
        }

        newArr.push(obj);
      }
    });

    if (newArr && newArr.length) {
      const first = newArr[0];

      const last = newArr.length > 2 ? newArr[newArr.length - 1] : null;

      if (first.funId === undefined) {
        allLeng -= first.leng;

        item.offset = item.offset + first.leng / 2 + 1;

        newArr.shift();
      }

      if (last && last.funId === undefined) {
        allLeng -= last.leng;

        newArr.pop();
      }
    }

    item.list = newArr;

    if (newArr.length) {
      item.finsAddress = newArr[0].finsAddress;

      item.addr = newArr[0].offsetId;

      item.leng = allLeng / 2;

      newArrList.push(item);
    }

    // if (isConsole) {
    //   console.log(allLeng);
    // }

    // console.log(allLeng);
  });

  return newArrList;
}

export function getDFFinsReadListFn(readData: any = [], writeData: any = []) {
  const arr = setOffsetNumFn([...readData, ...writeData], 'read');

  const obj = {};

  let plcReadList: any = [];

  for (const item of arr) {
    const { type = 'D', plcId = null } = item;

    if (plcId) {
      if (!obj[plcId]) {
        obj[plcId] = {
          D: [],
          M: []
        };
      }

      if (obj[plcId][type]) {
        obj[plcId][type].push(item);
      }
    }
  }

  for (const plc in obj) {
    if (obj[plc]) {
      const readList: any = [];

      let dList: any = [];

      let mList: any = [];

      for (const i in obj[plc]) {
        if (obj[plc][i] && obj[plc][i].length) {
          for (const item of obj[plc][i]) {
            if (item.list && item.list.length) {
              switch (i) {
                case 'D':
                  dList = [...dList, ...item.list];
                  break;
                case 'M':
                  mList = [...mList, ...item.list];
                  break;

                default:
                  break;
              }
            }
          }
        }
      }

      if (dList && dList.length) {
        const dObj = {};

        dList.sort((a, b) => a.offsetIdNum - b.offsetIdNum);

        dList = dList.reduce((cur, next) => {
          dObj[next.funId] ? '' : (dObj[next.funId] = true && cur.push(next));

          return cur;
        }, []);

        dList.map((item, _key) => {
          item.address = item.offsetIdNum;

          return item;
        });

        dList = resetArrFn(dList);

        // console.log(dList)

        dList.map(item => {
          item.finsAddress = `D${item.address}`;

          return item;
        });

        readList.push({
          code: 3,
          finsAddress: dList[0].finsAddress,
          // leng: dList.length,
          offset: 0,
          startOffset: dList[0].offsetIdNum,
          plcId: plc,
          type: 'D',
          list: dList
        });
      }

      if (mList && mList.length) {
        const mObj = {};

        mList.sort((a, b) => a.offsetIdNum - b.offsetIdNum);

        mList = mList.reduce((cur, next) => {
          mObj[next.funId] ? '' : (mObj[next.funId] = true && cur.push(next));

          return cur;
        }, []);

        mList.map(item => {
          item.address = item.offsetIdNum;

          return item;
        });

        mList = resetArrFn(mList);

        mList.map(item => {
          item.finsAddress = `W${Math.floor(item.offsetIdNum / 16)}.${
            item.offsetIdNum % 16
          }`;

          return item;
        });

        readList.push({
          code: 1,
          finsAddress: mList[0].finsAddress,
          // leng: dList.length,
          offset: 0,
          startOffset: mList[0].offsetIdNum,
          plcId: plc,
          type: 'M',
          list: mList
        });
      }

      plcReadList = [...plcReadList, ...setOffsetNumFn(readList, 'read', true)];

      // plcReadObj[plc] = setOffsetNumFn(readList, 'read', true);

      // console.log(setOffsetNumFn(readList));
    }
  }

  // console.log(obj)

  return plcReadList;
}

export function getMqttListFn(list = []) {
  const newList: any = [];

  if (list && list.length) {
    for (const item of list) {
      const { list: iList = [] } = item;

      if (iList && iList.length) {
        for (const lItem of iList) {
          const { name = null, funId = null } = lItem;

          if (name && funId) {
            newList.push({ name, funId });
          }
        }
      }
    }
  }

  return newList;
}

export function filterDFFinsReadArrFn(obj: any = {}, arr: any = []) {
  let newArr: any = [];

  if (obj && arr && arr.length) {
    const { addr = null, leng = null, modId = null } = obj;

    if (modId) {
      newArr = cloneDeep(arr);

      const obj = newArr.find(item => item.modId === modId);

      if (obj && obj.list) {
        newArr = obj.list;

        if (addr && leng) {
          const index = newArr.findIndex(item => item.offsetId === addr);

          newArr = newArr.slice(index, index + leng);
        }

        return newArr;
      }
    }
  }

  return newArr;
}

export const dfFinsAllReadList = getDFFinsReadListFn();

// console.log(dfFinsAllReadList);

export function getDFFinsWriteArrFn() {
  // const arr = writeData;

  return dfFinsAllReadList;
}

export const dFFinsAllWriteList: any = dfFinsAllReadList;

// console.log(dFFinsAllWriteList);

// console.log(getDFFinsWriteArrFn());

// console.log(getDFFinsReadArrFn());

export function filterDFFinsWriteArrFn(obj: any = {}) {
  // console.log(obj);
  if (!obj) {
    throw new Error('写入数据有误');
  }

  const { type = null, funId = null, plcId = null } = obj;

  let arr: any = dFFinsAllWriteList;

  let writeObj: any = null;

  if (!type || !funId) {
    throw new Error('写入数据有误');
  }

  if (plcId) {
    arr = [];

    for (const item of dFFinsAllWriteList) {
      const { plcId: iPlcId = null } = item;

      if (iPlcId === plcId) {
        arr.push(item);
      }
    }
  }

  const isFind = !arr.every(item => {
    const { type = null, list = [] } = item;

    if (item.type === type && list && list.length) {
      const lObj = list.find(lItem => lItem.funId === funId);

      if (lObj) {
        writeObj = lObj;

        return false;
      }
    }

    return true;
  });

  if (!isFind) {
    throw new Error(`无配置该funId:${funId}写入数据`);
  }

  return writeObj;
}

export function filterFinsWriteObjFn(obj: any = {}, arr = getDFFinsWriteArrFn()) {
  let lObj = null;

  if (!obj) {
    throw new Error('写入数据有误');
  }

  const { funId = null } = obj;

  if (!funId) {
    throw new Error('写入数据有误');
  }

  arr.every(item => {
    const { list = [] } = item;

    if (list && list.length) {
      lObj = list.find(lItem => lItem.funId === funId);

      if (lObj) {
        return false;
      }
    }

    return true;
  });

  if (!lObj) {
    throw new Error('找不到配置写入数据的值');
  }

  return lObj;
}
